package com.cskaoyan.javase.oop1._11static._5exercise;
/**
 * 读程序题
 * 首先找main方法,考虑main方法的执行
 * 但是不要忘记启动main方法触发类加载
 *
 * 整个过程中,类加载是连环触发的
 * 首先类加载Demo2,是通过启动main方法触发的,它率先开始类加载
 * 然后Demo2类中有静态成员变量cat需要创建对象
 * 然后触发Cat类的类加载
 * 在Cat类类加载过程中,需要创建Dog对象
 * 于是又触发Dog类的类加载
 *
 * 所以整个过程中,Dog类最后开始类加载,最先完成类加载
 *
 * Dog类完成类加载后,创建Dog对象,完成Cat类的类加载
 *
 * 所以整个程序的第一个输出是"dog"
 * 依赖于Cat类中的语句:
 * static Dog dog = new Dog();
 *
 * Cat类完成了类加载,于是可以创建Cat对象
 * 程序第二个输出的是"cat"
 *
 * 创建完毕Cat对象,完成Demo2的类加载
 * Demo2率先开始类加载,最后完成类加载
 *
 * 以上就是整个类加载的过程，会依次输出：
 * dog
 * cat
 *
 * 类加载Demo2结束，开始执行main方法
 * 于是输出"hello world!"
 *
 * 接下来需要创建Demo2的对象
 * 就不再考虑类加载了，并且这个案例中的三个类都已经类加载完毕，都不需要考虑类加载了。
 *
 * 于是直接创建Demo2对象
 * 找构造器，但是不执行构造器代码
 * 而是从上到下执行成员变量的显式赋值
 * 于是程序就输出"dog"
 * 最后找到构造器，于是输出"demo"
 *
 * 所以程序整体的输出是：
 * dog
 * cat
 * hello world!
 * dog
 * demo
 *
 *
 * @since 11:19
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo2 {
    // 和static int a = 10; 没有本质区别,都是静态成员变量的显式赋值
    static Cat cat = new Cat();
    Dog dog = new Dog();
    Dog dog2;
    static Dog dog3;

    // 在启动main方法之前,Demo2这个类要类加载
    public static void main(String[] args) {
        System.out.println("hello world!");
        Demo2 d = new Demo2();
    }

    public Demo2() {
        System.out.println("demo");
    }
}

class Cat {
    static Dog dog = new Dog();

    public Cat() {
        System.out.println("cat");
    }
}

class Dog {
    // 如果Dog完成类加载，又需要依赖于创建Demo2对象，咋办？ 挖个坑，后面填
    // static Demo2 d = new Demo2();

    public Dog() {
        System.out.println("dog");
    }
}